﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WebLayer;
using WebPageParser;
using System.Collections.Observable;

using SpeakupBackend.Classes;
using SpeakupBackend.Themes;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using SpeakupBackend.Stats;
using TableParsers;

namespace SpeakupBackend
{

    [Serializable]
    public class BackendContext
    {
        public ClubThemeCollection ClubThemes = new ClubThemeCollection();
        public GroupThemeCollection GroupThemes = new GroupThemeCollection();
        public WorkshopThemeCollection WorkshopThemes = new WorkshopThemeCollection();
        public BusinessThemeCollection BusinessThemes = new BusinessThemeCollection();
        public ClassList Classes = new ClassList();
        public PersonalStats Stats = new PersonalStats();
        public ObservableList<String> KnownSchools = new ObservableList<String>();

        [NonSerialized]
        LoginToken m_loginToken;
        public LoginToken LoginToken
        {
            get
            {
                if (m_loginToken == null)
                {
                    m_loginToken = new LoginToken("", "", "");
                }
                return m_loginToken;
            }
            set
            {
                m_loginToken = value;
            }
        }
        
        /// <summary>
        /// Loads all necessary data using default schemes
        /// </summary>
        public void Refresh()
        {           
            WorkshopThemes.ReloadFromXml("WorkshopThemes.xml");
            BusinessThemes.ReloadFromXml("BusinessThemes.xml");

            WebPageCache cache = new WebPageCache();
            cache.LoginToken = LoginToken;

            Stats.Refresh(cache);

            Classes.Refresh(ClassList.RefreshType.AllClasses, cache);
            

            ClubThemes.Clear();
            foreach (GroupTheme theme in GroupThemes)
            {
                theme.ClearClasses();
            }            

            AssignCurrentUnit2FutureClasses();
            ExtractClubThemes();
            AssignThemes2Classes();            
        }

        public void ExtractClubThemes()
        {
            var clubClasses = from n in Classes 
                              where n.Name.Type == ClassType.Club
                              select n;

            foreach (Class cl in clubClasses)
            {
                ClubLevelGroup levelGroup = ClubLevelGroup.ClubFactory.GetLevelGroup(Stats.Level);
                if (cl.Level != null)
                {
                    levelGroup = ClubLevelGroup.ClubFactory.GetLevelGroup(cl.Level);
                }

                ClubThemes.Add(new ClubTheme(cl.Name.Name, levelGroup));
            }
        }

        public void AssignCurrentUnit2FutureClasses()
        {
            var futureClasses = from n in Classes 
                                where n.CurrentStatus.IsFuture()
                                select n;

            foreach (Class cl in futureClasses)
            {
                cl.Unit = Stats.Unit;
            }
        }

        public void AssignThemes2Classes()
        {
            foreach (Class cl in Classes)
            {
                foreach (ClubTheme theme in ClubThemes)
                {
                    if (theme.IsCompatibleClass(cl))
                    {
                        theme.AddClass(cl);
                        cl.Theme = theme;
                    }
                }

                foreach (GroupTheme theme in GroupThemes)
                {
                    if (theme.IsCompatibleClass(cl))
                    {
                        theme.AddClass(cl);
                        cl.Theme = theme;
                    }
                }

                foreach (WorkshopTheme theme in WorkshopThemes)
                {
                    if (theme.IsCompatibleClass(cl))
                    {
                        theme.AddClass(cl);
                        cl.Theme = theme;
                    }
                }

                foreach (BusinessTheme theme in BusinessThemes)
                {
                    if (theme.IsCompatibleClass(cl))
                    {
                        theme.AddClass(cl);
                        cl.Theme = theme;
                    }
                }
            }            
        }

        public void DumpClasses()
        {
            var sortedCl = from n in Classes
                           orderby n.Level ascending, n.Name.Type ascending, Week.GetWeek(n.Time.Date) ascending
                           where WorkshopClassType.IsValidClassType(n.Name.Type)
                           select n;

            foreach (Class cl in sortedCl)
            {
                bool attended = false;
                if(cl.Theme != null)
                {
                    attended = cl.Theme.IsAttended;
                }

                Trace.WriteLine(String.Format("Class: Level - {0}, Unit - {1}, Type - {2}, Week - {3}, Attended - {4}",
                                              cl.Level, cl.Unit, cl.Name.Type, Week.GetWeek(cl.Time.Date), attended));
            }
        }


        #region Binary serialization

        public void Save(String fileName)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            using (FileStream fileStream = new FileStream(fileName, FileMode.Create))
            {
                formatter.Serialize(fileStream, this);
            }
        }

        public static BackendContext Load(String fileName)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            using (FileStream fileStream = new FileStream(fileName, FileMode.Open))
            {
                return (BackendContext)formatter.Deserialize(fileStream);
            }
        }

        #endregion
    }
}
